package sg.edu.nus.iss.jass.controller;

import java.util.ArrayList;
import java.util.List;

import sg.edu.nus.iss.jass.constant.ActionBtnContants;
import sg.edu.nus.iss.jass.constant.CommonConstants;
import sg.edu.nus.iss.jass.constant.ErrorConstants;
import sg.edu.nus.iss.jass.datastore.Transaction;
import sg.edu.nus.iss.jass.datastore.exception.DataStoreException;
import sg.edu.nus.iss.jass.dto.Action;
import sg.edu.nus.iss.jass.dto.Company;
import sg.edu.nus.iss.jass.dto.GeographicalLocation;
import sg.edu.nus.iss.jass.dto.JobAdvert;
import sg.edu.nus.iss.jass.dto.JobResponse;
import sg.edu.nus.iss.jass.dto.JobSeeker;
import sg.edu.nus.iss.jass.dto.Resume;
import sg.edu.nus.iss.jass.dto.Skill;
import sg.edu.nus.iss.jass.dto.SkillReference;
import sg.edu.nus.iss.jass.gui.ActionPanel;
import sg.edu.nus.iss.jass.gui.DefaultActionPanel;
import sg.edu.nus.iss.jass.gui.FormPanel;
import sg.edu.nus.iss.jass.gui.HeaderPanel;
import sg.edu.nus.iss.jass.gui.JobAdvertisementDetailFormPanel;
import sg.edu.nus.iss.jass.gui.JobAdvertisementFormPanel;
import sg.edu.nus.iss.jass.gui.JobAdvertisementModifyFormPanel;
import sg.edu.nus.iss.jass.gui.JobApplicationFormPanel;
import sg.edu.nus.iss.jass.gui.MainFrame;
import sg.edu.nus.iss.jass.persistence.ActionDAO;
import sg.edu.nus.iss.jass.persistence.CompanyDAO;
import sg.edu.nus.iss.jass.persistence.JobAdvertDAO;
import sg.edu.nus.iss.jass.persistence.JobResponseDAO;
import sg.edu.nus.iss.jass.persistence.JobSeekerDAO;
import sg.edu.nus.iss.jass.persistence.LocationDAO;
import sg.edu.nus.iss.jass.persistence.ResumeDAO;
import sg.edu.nus.iss.jass.persistence.SkillDAO;
import sg.edu.nus.iss.jass.privilege.JobSeekerRole;
import sg.edu.nus.iss.jass.privilege.Role;
import sg.edu.nus.iss.jass.privilege.SessionContext;
import sg.edu.nus.iss.jass.util.Util;


public class JobAdvertisementController {

	private MainFrame mainframe = null;
	
	private JobSeeker jobSeeker;
	private JobSeekerDAO jobSeekerDAO;
	private JobAdvertDAO jobAdvertDAO;
	private JobResponseDAO jobResponseDAO;
	private ResumeDAO resumeDAO;
	private SkillDAO skillDAO;
	private ActionDAO actionDAO;
	private JobAdvertisementFormPanel jobAdvertisementFormPanel = null;
	private JobAdvertisementDetailFormPanel jobAdvertisementDetailFormPanel = null;
	private JobAdvertisementModifyFormPanel jobAdvertisementModifyFormPanel = null;
	
	private JobApplicationFormPanel jobApplicationFormPanel = null;
	
	public JobAdvertisementController(){
		jobAdvertDAO = new JobAdvertDAO();
		jobResponseDAO = new JobResponseDAO();
		skillDAO = new SkillDAO();
		jobSeekerDAO = new JobSeekerDAO();
		actionDAO = new ActionDAO();
		resumeDAO = new ResumeDAO();
		this.mainframe = MainController.getInstance().getMainframe();
	}
	
	public void processAddJobAd(JobAdvert jobAdvert) {
		
		Transaction trans = null;
		try {
			trans = jobAdvertDAO.getTransaction();
		} catch (DataStoreException e) {
			//TODO handle exception or throw exception
		}
		
		if(trans != null){
			try {
				trans.startTransaction();
				if (jobAdvert.getSkills() != null) {
					skillDAO.saveSkills(jobAdvert.getSkills().toArray(new Skill[0]));
				}
				jobAdvertDAO.createJobAdvert(jobAdvert);
				trans.commit();
			} catch (DataStoreException e) {
				try {
					trans.rollback();
				} catch (DataStoreException e1) {
					e1.printStackTrace();
				}
				jobAdvertisementFormPanel.showMsg(ErrorConstants.ERROR_NO_DATA, false);
				return;
			}
		}
		jobAdvertisementFormPanel.displaySuccessfulMsg();
	}
	
	public void processApplyJob(JobResponse jobResponse) {
		Transaction trans = null;
		try {
			trans = jobAdvertDAO.getTransaction();
		} catch (DataStoreException e) {
			//TODO handle exception or throw exception
		}

		if(trans != null){
			try {
				trans.startTransaction();
				Action action = actionDAO.getActionByStatus(CommonConstants.ACTION_APPLIED);
				jobResponse.setAction(action);
				if (jobResponse.getSkill() != null && jobResponse.getSkill().size()>0) {
					skillDAO.saveSkills(jobResponse.getSkill().toArray(new Skill[0]));
				}				
				jobResponseDAO.createJobResponse(jobResponse);
				trans.commit();
			} catch (DataStoreException e) {
				try {
					trans.rollback();
				} catch (DataStoreException e1) {
					e1.printStackTrace();
				}
				jobApplicationFormPanel.showMsg(ErrorConstants.ERROR_NO_DATA, false);
			}
		}
		jobApplicationFormPanel.displayCompletionMsg();
	}
	
	public void processDeleteJobAd(JobAdvert jobAdvert)throws Exception {
		Transaction trans = null;
		try {
			trans = jobAdvertDAO.getTransaction();
		} catch (DataStoreException e) {
			//TODO handle exception or throw exception
		}
		
		if(trans != null){
			try {
				trans.startTransaction();
				jobAdvert.setStatus(false);
				jobAdvertDAO.updateJobAdvert(jobAdvert);
				trans.commit();
			} catch (DataStoreException e) {
				try {
					trans.rollback();
				} catch (DataStoreException e1) {
					e1.printStackTrace();
				}
				throw e;
				//formPanel.showMsg(ErrorConstants.ERROR_NO_DATA, false);
			}
		}
	}
	
	public void processModifyJobAd(JobAdvert jobAdvert) {
		Transaction trans = null;
		try {
			trans = jobAdvertDAO.getTransaction();
		} catch (DataStoreException e) {
			//TODO handle exception or throw exception
		}
		
		if(trans != null){
			try {
				trans.startTransaction();
				if (jobAdvert.getSkills() != null) {
					skillDAO.saveSkills(jobAdvert.getSkills().toArray(new Skill[0]));
				}				
				jobAdvertDAO.updateJobAdvert(jobAdvert);
				trans.commit();
			} catch (DataStoreException e) {
				try {
					trans.rollback();
				} catch (DataStoreException e1) {
					e1.printStackTrace();
				}
				jobAdvertisementModifyFormPanel.showMsg(ErrorConstants.ERROR_UNKNOWN, false);
				return;
				//formPanel.showMsg(ErrorConstants.ERROR_NO_DATA, false);
			}
		}
		jobAdvertisementModifyFormPanel.displaySuccessfulMsg();
	}
	
	public void processWithdrawJobAd(JobAdvert jobAdvert) {
		
	}
	
	public void startAddJobAd() {
		List<SkillReference> skills = getAllSkills(null);
		List<Company> companies = getAllCompanies(null);
		List<GeographicalLocation> locations = getAllLocations(null);		
		jobAdvertisementFormPanel = new JobAdvertisementFormPanel(mainframe, new DefaultActionPanel(ActionBtnContants.SUBMIT,ActionBtnContants.RESET), 
				new HeaderPanel("Add Job Advertisement"), skills, locations, companies);
		jobAdvertisementFormPanel.setController(this);
		jobAdvertisementFormPanel.show();
	}
	
	public void startApplyJob(String jobAdvertID) {
		ActionPanel actionPanel = null;
		List<Resume> resumes = null;
		JobAdvert jobAdvert = getJobAdvertById(jobAdvertID);
		actionPanel = new DefaultActionPanel(ActionBtnContants.APPLY_JOB, ActionBtnContants.CANCEL);
		String jobSeekerName = SessionContext.getUser().getUsername();
		System.out.println("jobSeekerName :" + jobSeekerName);
		
		try {
			jobSeeker = jobSeekerDAO.getJobSeekerByID(jobSeekerName);
			System.out.println("jobSeeker :" + jobSeeker);
			resumes = resumeDAO.findResumes(jobSeeker);
			
			for (Resume resume : resumes ){
				List<String> skillIds =  resume.getIdList(resume.getSkillIds());
				List<Skill> skills = skillDAO.getSkillByIds(skillIds);
				if (skills != null) {
					for(Skill skill: skills){
						skill.setSkillRef(skillDAO.getSkillRefById(skill.getSkillRefId()));
					}
				}
				resume.setSkillDetails((ArrayList<Skill>) skills);
			}
			
			
			
			
		} catch (DataStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if (jobApplicationFormPanel != null)
				jobApplicationFormPanel.showMsg(ErrorConstants.ERROR_RETREIVE_DATA, false);
		}
		
		
		jobApplicationFormPanel = new JobApplicationFormPanel(mainframe, actionPanel, 
				new HeaderPanel("Apply Job"), jobAdvert,jobSeeker,resumes);
		
		jobApplicationFormPanel.setController(this);
		jobApplicationFormPanel.show();
		
	}
	
	public void startJobAdDetails(String jobAdvertID) {
		JobAdvert jobAdvert = getJobAdvertById(jobAdvertID);
		ActionPanel actionPanel = null;
		if (SessionContext.getUser().getRole() instanceof JobSeekerRole) {
			actionPanel = new DefaultActionPanel(ActionBtnContants.APPLY_JOB, ActionBtnContants.CANCEL);
		} else {
			actionPanel = new DefaultActionPanel(ActionBtnContants.CANCEL);
		}
		jobAdvertisementDetailFormPanel = new JobAdvertisementDetailFormPanel(mainframe, actionPanel, new HeaderPanel("View Job Advertisement"), jobAdvert);
		jobAdvertisementDetailFormPanel.setController(this);
		jobAdvertisementDetailFormPanel.show();
	}
	
	public void validate() {
		
	}
	
	public void startModifyJobAd(String jobAdvertID) {
		List<SkillReference> skills = getAllSkills(null);
		List<Company> companies = getAllCompanies(null);
		List<GeographicalLocation> locations = getAllLocations(null);
		JobAdvert jobAdvert = getJobAdvertById(jobAdvertID);
		jobAdvertisementModifyFormPanel = new JobAdvertisementModifyFormPanel(mainframe, new DefaultActionPanel(ActionBtnContants.UPDATE,ActionBtnContants.CANCEL), 
				new HeaderPanel("Modify Job Advertisement"), skills, locations, companies, jobAdvert);
		jobAdvertisementModifyFormPanel.setController(this);
		jobAdvertisementModifyFormPanel.show();
	}

	public List<SkillReference> getAllSkills(FormPanel formPanel){
		try {
			return (new SkillDAO()).getAllSkills();
		} catch (DataStoreException e) {
			e.printStackTrace();
			if (formPanel != null) 
				formPanel.showMsg(ErrorConstants.ERROR_RETREIVE_DATA, false);
		}
		return null;
	}
	public List<Company> getAllCompanies(FormPanel formPanel){
		try {
			return (new CompanyDAO()).getAllCompanies();
		} catch (DataStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if (formPanel != null)
				formPanel.showMsg(ErrorConstants.ERROR_RETREIVE_DATA, false);
		}
		return null;
	}
	
	public List<GeographicalLocation> getAllLocations(FormPanel formPanel){
		try {
			return (new LocationDAO()).getAllLocations();
		} catch (DataStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if (formPanel != null)
				formPanel.showMsg(ErrorConstants.ERROR_RETREIVE_DATA, false);
		}
		return null;
	}

	public void processDeleteJobAd(List<JobAdvert> selectedJobList) throws Exception {
		Transaction trans = null;
		try {
			trans = jobAdvertDAO.getTransaction();
		} catch (DataStoreException e) {
			//TODO handle exception or throw exception
		}
		
		if(trans != null){
			try {
				trans.startTransaction();
				for (int i=0; i < selectedJobList.size(); i++) {
					selectedJobList.get(i).setStatus(false);
				}
				jobAdvertDAO.updateJobAdverts(selectedJobList);
				trans.commit();
			} catch (DataStoreException e) {
				try {
					trans.rollback();
				} catch (DataStoreException e1) {
					e1.printStackTrace();
				}
				jobAdvertisementFormPanel.showMsg(ErrorConstants.ERROR_UNKNOWN, false);
				return;
				//throw e;
			}
		}
		jobAdvertisementFormPanel.displaySuccessfulMsg();
	}
	
	public JobAdvert getJobAdvertById(String jobAdvertID) {
		Transaction trans = null;
		JobAdvert result = null;
		CompanyDAO companyDAO = new CompanyDAO();
		SkillDAO skillDAO = new SkillDAO();
		LocationDAO locationDAO = new LocationDAO(); 
		try {
			trans = jobAdvertDAO.getTransaction();
		} catch (DataStoreException e) {
			//TODO handle exception or throw exception
		}
		
		if(trans != null){
			try {
				trans.startTransaction();
				result = jobAdvertDAO.findJobAd(jobAdvertID);
				if (result.getCompanyId() != null && !"".equals(result.getCompanyId())) {
					result.setCompany(companyDAO.getCompanyById(result.getCompanyId()));
				}
				if (result.getSkillIds() != null && !"".equals(result.getSkillIds())) {
					result.setSkills(skillDAO.getSkillByIds(result.getIdList(result.getSkillIds())));
					if (result.getSkills() != null) {
    					for (int i=0; i < result.getSkills().size(); i++) {
    					    if (result.getSkills().get(i).getSkillRefId() != null && !"".equals(result.getSkills().get(i).getSkillRefId())) {
    					        result.getSkills().get(i).setSkillRef(skillDAO.getSkillRefById(result.getSkills().get(i).getSkillRefId()));
    					    }
    					}
					}
				}
				if (result.getGeographicalLocationId() != null && !"".equals(result.getGeographicalLocationId())) {
					result.setGeographicalLocation(locationDAO.getLocationById(result.getGeographicalLocationId()));
				}
				trans.commit();
			} catch (DataStoreException e) {
				try {
					trans.rollback();
				} catch (DataStoreException e1) {
					e1.printStackTrace();
				}
			}
		}
		return result;
	}
	
}
